/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact 824069438@qq.com
 *  
 */
package org.zfes.snowy.auth.shiro.filter.authc;


import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.zfes.snowy.auth.AuthConsts;
import org.zfes.snowy.auth.shiro.handlers.IAuthecFailureHandler;
import org.zfes.snowy.auth.shiro.handlers.IAuthecSuccessHandler;
import org.zfes.snowy.auth.shiro.handlers.IUnAuthecHandler;

public abstract class SnowyAuthenticationFilter extends SnowyAccessControlFilter implements SSOSyncInterface{

    protected IUnAuthecHandler authecUnAuthecHandler;
    
    protected IAuthecSuccessHandler  authecSuccessHandler;
    
    protected IAuthecFailureHandler  authecFailureHandler;
    
    protected String loginPortUrl = AuthConsts.DEFAULT_LOGIN_PORT_URL;
    
	protected String loginSubmitUrl = AuthConsts.LOGIN.DEFAULT_LOGIN_SUBMIT_URL;
    
    protected Long clientAuthorizationCacheVersion=AuthConsts.CLIENT_AUTHORIZATION_CACHE_VERSION;
    
    protected Boolean isEnableSnowySSOClient = false;//支持sso
  
    protected Integer maxSession = 1 ;
    
    protected Boolean isEnableSessionStrategy;
    
    protected Boolean isEnableCSRFToken=false;
    
    private String appKey;
    
	@SuppressWarnings("serial")
	public static final Set<String> supportsLoginOrgins=new HashSet<String>(){{this.add("PC");this.add("MOB");this.add("WEICHAT");}};
    
	@Override 
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		Subject subject = getSubject(request, response);
	     boolean isAuthenticated= subject.isAuthenticated();
		 if( isAuthenticated && isEnableSnowySSOClient ){
			syncClientCache(subject.getSession(),appKey);
		 }
		 if(isEnableCSRFToken) {
			String token=WebUtils.toHttp(request).getHeader(AuthConsts.HEADER.CSRF_TOKEN);
			return token.equals(subject.getSession().getAttribute(AuthConsts.SESSION.SESSION_CSRF_TOKEN));
		 }
        return isAuthenticated&&customeExtendAccess( request,  response);
    }

	 protected  boolean customeExtendAccess(ServletRequest request, ServletResponse response) {
		//deafult  to do nothing
		 return true;
	 }
	
	  protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
		  return pathsMatch( getLoginSubmitUrl() ,  request);
	  }
	  protected boolean isLoginPortUrlRequest(ServletRequest request, ServletResponse response) {
		 return pathsMatch(getLoginPortUrl(), request);
	  }
	  
	  
	  
	 @Override
	 protected void cleanup(ServletRequest request, ServletResponse response, Exception existing) throws ServletException, IOException {
	    if (existing instanceof UnauthenticatedException || (existing instanceof ServletException && existing.getCause() instanceof UnauthenticatedException)){
	        try {
	                onAccessDenied(request, response);
	                existing = null;
	            } catch (Exception e) {
	                existing = e;
	            }
	        }
	        super.cleanup(request, response, existing);

	 }

	public IUnAuthecHandler getAuthecUnAuthecHandler() {
		return authecUnAuthecHandler;
	}

	public void setAuthecUnAuthecHandler(IUnAuthecHandler authecUnAuthecHandler) {
		this.authecUnAuthecHandler = authecUnAuthecHandler;
	}

	public IAuthecSuccessHandler getAuthecSuccessHandler() {
		return authecSuccessHandler;
	}

	public void setAuthecSuccessHandler(IAuthecSuccessHandler authecSuccessHandler) {
		this.authecSuccessHandler = authecSuccessHandler;
	}

	public IAuthecFailureHandler getAuthecFailureHandler() {
		return authecFailureHandler;
	}

	public void setAuthecFailureHandler(IAuthecFailureHandler authecFailureHandler) {
		this.authecFailureHandler = authecFailureHandler;
	}

	public Long getClientAuthorizationCacheVersion() {
		return clientAuthorizationCacheVersion;
	}

	public void setClientAuthorizationCacheVersion(Long clientAuthorizationCacheVersion) {
		this.clientAuthorizationCacheVersion = clientAuthorizationCacheVersion;
	}

	public Boolean getIsEnableSnowySSOClient() {
		return isEnableSnowySSOClient;
	}

	public void setIsEnableSnowySSOClient(Boolean isEnableSnowySSOClient) {
		this.isEnableSnowySSOClient = isEnableSnowySSOClient;
	}
	public String getLoginPortUrl() {
		return loginPortUrl;
	}
	public void setLoginPortUrl(String loginPortUrl) {
		this.loginPortUrl = loginPortUrl;
	}
	public String getLoginSubmitUrl() {
		return loginSubmitUrl;
	}
	public void setLoginSubmitUrl(String loginSubmitUrl) {
		this.loginSubmitUrl = loginSubmitUrl;
	}

	public Integer getMaxSession() {
		return maxSession;
	}

	public void setMaxSession(Integer maxSession) {
		this.maxSession = maxSession;
	}


	public Boolean getIsEnableSessionStrategy() {
		return isEnableSessionStrategy;
	}

	public void setIsEnableSessionStrategy(Boolean isEnableSessionStrategy) {
		this.isEnableSessionStrategy = isEnableSessionStrategy;
	}

	public Boolean getIsEnableCSRFToken() {
		return isEnableCSRFToken;
	}

	public void setIsEnableCSRFToken(Boolean isEnableCSRFToken) {
		this.isEnableCSRFToken = isEnableCSRFToken;
	}

	public String getAppKey() {
		return appKey;
	}

	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}


	 
}
